#include <stdlib.h>
#include <stdio.h>

#include "defs.h"

#define AS_PACKAGE    "@AS_PACKAGE@"
#define AS_CLASS_DECL "@AS_CLASS_DECL@"

/*  The banner used here should be replaced with an #ident directive	*/
/*  if the target C compiler supports #ident directives.		*/
/*									*/
/*  If the skeleton is changed, the banner should be changed so that	*/
/*  the altered version can easily be distinguished from the original.	*/

char *as_banner[] = {
	"//### This file created by byacc 1.8 / ActionScript 3 extension 0.1)",
	"//### ActionScript support added 16 April 2008, Gabriele Farina",
	"//### Please send bug reports to gabriele@alittleb.it",
	"//### private yysccsid = \"@(#)yaccpar	1.8 (Berkeley +Cygnus.28) 01/20/91\";",
	"\n\n",
	AS_PACKAGE,
	"\n\n",
	0
};

char *as_tables[] = {
	"",
	0
};

char *as_header[] = {
	"",
	"",
	"",
	"/*",
	" * Encapsulates yacc() parser functionality in an ActionScript 3 class",
	" */",
	AS_CLASS_DECL,
	"{",
	"	private var yydebug: Boolean;	// debug output desired ?",
	"	private var yynerrs: int;		// number of errors so far",
	"	private var yyerrflag: int;		// was there an error ?",
	"	private var yychar: int;		// the current working character",
	"",
	"",
	"	public function debug( msg: String ): void",
	"	{",
	"		if( yydebug )",
	"		{",
	"			trace( msg );",
	"		}",
	"	}",
	"",
	"	public function yyerror( msg: String ): void",
	"	{",
	"	    trace( \"ERROR: \" + msg );",
	"	}",
	"",
	"	private var statestk: Array;	// state stack",
	"	private var stateptr: int;          ",
	"	private var stateptrmax: int; 		// highest index of stackptr",
	"	private var statemax: int;			// state when highest index reached",
	"",
	"	public function state_push( state: int ): void",
	"	{",
	"		statestk[ ++stateptr ] = state;",
	"",
	"		if( stateptr > statemax )",
	"		{",
	"			statemax = state;",
	"			stateptrmax = stateptr;",
	"		}",
	"	}",
	"",
	"	public function state_pop(): int",
	"	{",
	"		if( stateptr < 0 )                 //underflowed?",
	"		{",
	"			return -1;",
	"		}",
	"",
	"		return statestk[ stateptr-- ];",
	"	}",
	"",
	"	public function state_drop( cnt: int ): void",
	"	{",
	"		var ptr: int = ( stateptr - cnt );",
	"",
	"		if( ptr >= 0 )",
	"		{",
	"			stateptr = ptr;",
	"		}",
	"	}",
	"",
	"	public function state_peek( relative: int ): int",
	"	{",
	"		var ptr: int = ( stateptr - relative );",
	"",
	"		if( ptr < 0 )",
	"		{",
	"			return -1;",
	"		}",
	"",
	"		return statestk[ ptr ];",
	"	}",
	"",
	"	public function init_stacks(): Boolean",
	"	{",
	"		statestk = new Array();",
	"		stateptr = -1;",
	"		statemax = -1;",
	"		stateptrmax = -1;",
	"		val_init();",
	"",
	"		return true;",
	"	}",
	"",
	"	public function yylex(): int",
	"	{",
	"		trace(\"cascjaskjhcajkshgcjkcs\");",
	"		return 0;",
	"	}",
	"",
	"	public function dump_stacks( count: int ): void",
	"	{",
	"		trace( \"=index==state====value=     s:\" + stateptr + \"  v:\" + get_valptr() );",
	"",
	"		for( var i: int = 0; i < count; ++i )",
	"		{",
	"			trace( \" \" + i + \"    \" + statestk[ i ] + \"      \" + get_valstk()[ i ] );",
	"		}",
	"",
	"		trace( \"======================\" );",
	"	}",
	0
};

char *as_body[] = {
	"public function yylexdebug( state: int , ch: int): void",
	"{",
	"	var s: String;",
	"	",
	"	if( ch < 0 )",
	"	{",
	"		ch = 0;",
	"	}",
	"	",
	"	if( ch <= YYMAXTOKEN ) //check index bounds",
	"	{",
	"		s = yyname[ ch ];		//now get it",
	"	}",
	"	",
	"	if( s == null )",
	"	{",
	"		s = \"illegal-symbol\";",
	"	}",
	"",
	"	debug( \"state \" + state + \", reading \" + ch + \" (\" + s + \")\" );",
	"}",
	"",
	"private var yyn: int;		// next next thing to do",
	"private var yym: int;",
	"private var yystate: int;	// current parsing state from state table",
	"private var yys: String;	// current token string",
	"",
	"public function yyparse(): int",
	"{",
	"	var doaction: Boolean = false;",
	"	",
	"	init_stacks();",
	"	",
	"	yynerrs = 0;",
	"	yyerrflag = 0;",
	"	yychar = -1;	// impossible char forces a read",
	"	yystate = 0;	// initial state",
	"	",
	"	state_push( yystate );	//save it",
	"	",
	"	while( true )	// until parsing is done, either correctly, or w/error",
	"	{",
	"		doaction = true;",
	"		",
	"		if( yydebug )",
	"		{",
	"			debug( \"loop\" );",
	"		}",
	"		",
	"		//#### NEXT ACTION (from reduction table)",
	"		yyn = yydefred[ yystate ];",
	"		while( yyn == 0 )",
	"		{",
	"			if( yydebug )",
	"			{",
	"				debug( \"yyn: \" + yyn + \"	state: \" + yystate + \"	yychar: \" + yychar );",
	"			}",
	"			",
	"			if( yychar < 0 )	//we want a char?",
	"			{",
	"				yychar = yylex();	//get next token",
	"				if( yydebug )",
	"				{",
	"					debug( \" next yychar: \" + yychar );",
	"				}",
	"				",
	"				// #### ERROR CHECK ####",
	"				if( yychar < 0 )	//it it didn't work/error",
	"				{",
	"					yychar = 0;		//change it to default string (no -1!)",
	"					",
	"					if( yydebug )",
	"					{",
	"						yylexdebug( yystate, yychar );",
	"					}",
	"				}",
	"			}",
	"			",
	"			yyn = yysindex[ yystate ];	//get amount to shift by (shift index)",
	"			",
	"			if( ( yyn != 0 ) && ( yyn += yychar ) >= 0 && yyn <= YYTABLESIZE && yycheck[ yyn ] == yychar )",
	"			{",
	"				if( yydebug )",
	"				{",
	"					debug( \"state \" + yystate + \", shifting to state \" + yytable[ yyn ] );",
	"				}",
	"				",
	"				//#### NEXT STATE ####",
	"				yystate = yytable[ yyn ];	//we are in a new state",
	"				state_push( yystate );		//save it",
	"				val_push( yylval );			//push our lval as the input for next rule",
	"				yychar = -1;				//since we have 'eaten' a token, say we need another",
	"				",
	"				if( yyerrflag > 0 )			//have we recovered an error?",
	"				{",
	"					--yyerrflag;			//give ourselves credit",
	"				}",
	"				",
	"				doaction = false;			//but don't process yet",
	"				break;",
	"			}",
	"",
	"			yyn = yyrindex[ yystate ];	//reduce",
	"			if( ( yyn !=0 ) && ( yyn += yychar ) >= 0 && yyn <= YYTABLESIZE && yycheck[ yyn ] == yychar )",
	"			{	 //we reduced!",
	"				if( yydebug )",
	"				{",
	"					debug( \"reduce\" );",
	"				}",
	"				",
	"				yyn = yytable[ yyn ];",
	"				doaction = true; 		//get ready to execute",
	"				break;					//drop down to actions",
	"			}else //ERROR RECOVERY",
	"			{",
	"				if( yyerrflag == 0 )",
	"				{",
	"					yyerror( \"syntax error\" );",
	"					yynerrs++;",
	"				}",
	"				",
	"				if ( yyerrflag < 3 )	//low error count?",
	"				{",
	"					yyerrflag = 3;",
	"					while( true )	 //do until break",
	"					{",
	"						if( stateptr < 0 )	 //check for under & overflow here",
	"						{",
	"							yyerror( \"stack underflow. aborting...\" );	//note lower case 's'",
	"							return 1;",
	"						}",
	"						",
	"						yyn = yysindex[ state_peek( 0 ) ];",
	"						if ( ( yyn != 0 ) && ( yyn += YYERRCODE ) >= 0 && yyn <= YYTABLESIZE && yycheck[ yyn ] == YYERRCODE )",
	"						{",
	"							if( yydebug )",
	"							{",
	"								debug( \"state \" + state_peek( 0 ) + \", error recovery shifting to state \" + yytable[ yyn ] + \" \" );",
	"							}",
	"							",
	"							yystate = yytable[ yyn ];",
	"							state_push( yystate );",
	"							val_push( yylval );",
	"							doaction = false;",
	"							break;",
	"						}else",
	"						{",
	"							if( yydebug )",
	"							{",
	"								debug( \"error recovery discarding state \" + state_peek( 0 ) + \" \" );",
	"							}",
	"								",
	"							if( stateptr < 0 )	 //check for under & overflow here",
	"							{",
	"								yyerror( \"Stack underflow. aborting...\" );	//capital 'S'",
	"								return 1;",
	"							}",
	"							",
	"							state_pop();",
	"							val_pop();",
	"						}",
	"					}",
	"				}else						//discard this token",
	"				{",
	"					if( yychar == 0 )",
	"					{",
	"						return 1; //yyabort",
	"					}",
	"					",
	"					if( yydebug )",
	"					{",
	"						yys = \"illegal-symbol\";",
	"						",
	"						if( yychar <= YYMAXTOKEN )",
	"						{",
	"							yys = yyname[ yychar ];",
	"						}",
	"						",
	"						debug( \"state \" + yystate + \", error recovery discards token \" + yychar + \" (\" + yys + \")\" );",
	"					}",
	"					",
	"					yychar = -1;	//read another",
	"				}",
	"			}",
	"			",
	"			yyn = yydefred[ yystate ];",
	"		}",
	"		",
	"		if ( !doaction )	 		//any reason not to proceed?",
	"		{",
	"			continue;				//skip action",
	"		}",
	"		",
	"		yym = yylen[ yyn ];			//get count of terminals on rhs",
	"		",
	"		if( yydebug )",
	"		{",
	"			debug( \"state \" + yystate + \", reducing \" + yym + \" by rule \" + yyn + \" (\" + yyrule[ yyn ] + \")\" );",
	"		}",
	"		",
	"		if( yym > 0 )				//if count of rhs not 'nil'",
	"		{",
	"			yyval = val_peek( yym - 1 ); //get current semantic value",
	"		}",
	"		",
	"		/* switch(yyn) */",
	"		{",
	"			//########## USER-SUPPLIED ACTIONS ##########",
	0
};

char *as_trailer[] = {
	"		//########## END OF USER-SUPPLIED ACTIONS ##########",
	"		}",
	"		",
	"		//#### Now let's reduce... ####",
	"		if( yydebug )",
	"		{",
	"			debug( \"reduce\" );",
	"		}",
	"		",
	"		state_drop( yym );					//we just reduced yylen states",
	"		yystate = state_peek( 0 );		 	//get new state",
	"		val_drop( yym );				   	//corresponding value drop",
	"		yym = yylhs[ yyn ];					//select next TERMINAL(on lhs)",
	"		",
	"		if( yystate == 0 && yym == 0 )		//done? 'rest' state and at first TERMINAL",
	"		{",
	"			debug( \"After reduction, shifting from state 0 to state \" + YYFINAL );",
	"			",
	"		  	yystate = YYFINAL;				//explicitly say we're done",
	"		  	state_push( YYFINAL );			//and save it",
	"			val_push( yyval );				//also save the semantic value of parsing",
	"			",
	"		  	if( yychar < 0 )				//we want another character?",
	"			{",
	"				yychar = yylex();			//get next character",
	"				if( yychar < 0 )",
	"				{",
	"					yychar = 0;				//clean, if necessary",
	"				}",
	"				",
	"				if( yydebug )",
	"				{",
	"					yylexdebug( yystate, yychar );",
	"				}",
	"			}",
	"			",
	"			if( yychar == 0 )				//Good exit (if lex returns 0 ;-)",
	"			{",
	"				break;				 		//quit the loop--all DONE",
	"			}",
	"		} else								//else not done yet",
	"		{						 			//get next state and push, for next yydefred[]",
	"			yyn = yygindex[ yym ];			//find out where to go",
	"			if( ( yyn != 0 ) && ( yyn += yystate ) >= 0 && yyn <= YYTABLESIZE && yycheck[ yyn ] == yystate )",
	"			{",
	"				yystate = yytable[ yyn ];	//get new state",
	"			}else",
	"			{",
	"				yystate = yydgoto[ yym ];	//else go to new defred",
	"			}",
	"			",
	"			debug( \"after reduction, shifting from state \" + state_peek( 0 ) + \" to state \" + yystate );",
	"		  	state_push( yystate );			//going again, so push state & val...",
	"		  	val_push( yyval );				//for next action",
	"		}",
	"	}//main loop",
	"	",
	"	return 0;//yyaccept!!",
	"}",
	"",
	"}",
	"}", // End the package
	0
};


void write_section(const char *section[])
{
	int i;
	FILE *fp;

	fp = code_file;
	for (i = 0; section[i]; ++i)
	{
		++outline;
		if (strcmp(section[i], AS_PACKAGE) == 0)	/* ActionScript package name, if any */
		{
			fprintf(fp, "package %s\n{\n", as_package_name);
		} else if (strcmp(section[i], AS_CLASS_DECL) == 0)
		{
			if (as_class_name && strlen(as_class_name) > 0)
				fprintf(fp, "public class %s\n", as_class_name);
			else
				fprintf(fp, "public class Parser\n");
			if (as_extends_name && strlen(as_extends_name) > 0)
				fprintf(fp, "             extends %s\n", as_extends_name);
		} else
			fprintf(fp, "%s\n", section[i]);
	}
}
